package com.xc.file.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xc.core.bean.PagingBean;
import com.xc.core.dto.FileDto;
import com.xc.core.dto.PagingDto;
import com.xc.core.enums.EffectStatus;
import com.xc.core.enums.RedisPrefix;
import com.xc.core.enums.RedisTime;
import com.xc.core.utils.RedisUtils;
import com.xc.core.utils.ServiceUtils;
import com.xc.file.bean.QueryShareFolderBean;
import com.xc.file.bean.ShareBean;
import com.xc.file.config.Constants;
import com.xc.file.dto.FolderDto;
import com.xc.file.dto.FolderFileDto;
import com.xc.file.dto.ShareCodeDto;
import com.xc.file.dto.ShareDto;
import com.xc.file.entity.FileEntity;
import com.xc.file.entity.FolderEntity;
import com.xc.file.entity.ShareEntity;
import com.xc.file.entity.ShareFolderFileEntity;
import com.xc.file.enums.FailCode;
import com.xc.file.mapper.FileMapper;
import com.xc.file.mapper.FolderMapper;
import com.xc.file.mapper.ShareFolderFileMapper;
import com.xc.file.mapper.ShareMapper;
import com.xc.file.model.DownloadModel;
import com.xc.file.model.ShareIdModel;
import com.xc.file.service.FileService;
import com.xc.file.service.FolderService;
import com.xc.file.service.ShareService;
import com.xc.tool.utils.ObjectUtils;
import com.xc.tool.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>共享文件实现</p>
 *
 * @author xc
 * @version v1.0
 */
@Service
@Slf4j
public class ShareServiceImpl extends ServiceImpl<ShareMapper, ShareEntity> implements ShareService {

    @Autowired
    private ShareFolderFileMapper shareFolderFileMapper;
    @Autowired
    private FolderService folderService;
    @Autowired
    private FolderMapper folderMapper;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private ShareMapper shareMapper;
    @Autowired
    private FileService fileService;
    @Autowired
    private Constants constants;

    @Override
    @Transactional
    public ShareDto createUserShare(String userId, ShareBean shareBean) {
        //创建共享文件
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setValidTime(shareBean.getValidTime());
        if (shareBean.getNeedCode() == 0) {
            String drawCode = StringUtils.random(6);
            shareEntity.setDrawCode(drawCode);
        }
        shareEntity.setRemark(shareBean.getRemark());
        shareEntity.setUserId(userId);
        shareEntity.setCode(StringUtils.generateOnlyId(constants.getMachineId()));
        if (!this.save(shareEntity)) {
            throw FailCode.CREATE_SHARE_FILE_FAIL.getOperateException();
        }
        // 查询所有文件夹
        List<FolderEntity> folders = new ArrayList<>();
        List<FileEntity> files = new ArrayList<>();
        folderService.addFolderFile(folders, files, shareBean.getFolderIds(), shareBean.getFileIds(), userId);
        // 共享文件夹
        String folderName = null;
        for (FolderEntity folderEntity : folders) {
            for (String folderId : shareBean.getFolderIds()) {
                if (folderId.equals(folderEntity.getId()) && folderName == null) {
                    folderName = folderEntity.getName();
                }
            }
            // 验证是否可以共享
            if (!userId.equals(folderEntity.getUserId())) {
                throw FailCode.NOT_SHARE_OTHERS_FOLDER.getOperateException();
            }
            ShareFolderFileEntity share = new ShareFolderFileEntity();
            share.setShareId(shareEntity.getId());
            share.setFolderId(folderEntity.getId());
            share.setIsRoot(1);
            for (String id : shareBean.getFolderIds()) {
                if (id.equals(folderEntity.getId())) {
                    share.setIsRoot(0);
                }
            }
            if (!retBool(shareFolderFileMapper.insert(share))) {
                throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
        }
        // 共享文件
        String fileName = null;
        for (FileEntity fileEntity : files) {
            for (String fileId : shareBean.getFileIds()) {
                if (fileId.equals(fileEntity.getId()) && fileName == null) {
                    fileName = fileEntity.getName();
                }
            }
            // 验证是否可以共享
            if (!userId.equals(fileEntity.getUserId())) {
                throw FailCode.NOT_SHARE_OTHERS_FILE.getOperateException();
            }
            ShareFolderFileEntity share = new ShareFolderFileEntity();
            share.setShareId(shareEntity.getId());
            share.setFileId(fileEntity.getId());
            share.setIsRoot(1);
            for (String id : shareBean.getFileIds()) {
                if (id.equals(fileEntity.getId())) {
                    share.setIsRoot(0);
                }
            }
            if (!retBool(shareFolderFileMapper.insert(share))) {
                throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
        }
        // 货物文件名称
        String name = "";
        if (folders.size() > 0 && folderName != null) {
            name = folderName;
        }
        if (folders.size() > 0 && files.size() > 0 && fileName != null) {
            name += "，";
        }
        if (files.size() > 0 && fileName != null) {
            name += fileName;
        }
        // 更新共享名称
        if (shareBean.getFileIds().size() > 1 || shareBean.getFolderIds().size() > 1) {
            name = name + "，等";
        }
        shareEntity.setName(name);
        if (!this.updateById(shareEntity)) {
            throw FailCode.CREATE_SHARE_FILE_FAIL.getOperateException();
        }
        return ObjectUtils.convert(new ShareDto(), shareEntity);
    }

    @Override
    public PagingDto<ShareDto> getUserSharePage(String userId, Integer current, PagingBean pagingBean, ShareBean shareBean) {
        ShareEntity shareEntity = ObjectUtils.convert(new ShareEntity(), shareBean);
        shareEntity.setUserId(userId);
        QueryWrapper<ShareEntity> queryWrapper = ServiceUtils.queryData(pagingBean, shareEntity);
        IPage<ShareEntity> iPage = this.page(new Page<>(current, pagingBean.getSize()), queryWrapper);
        return new PagingDto<>(iPage.getTotal(), ObjectUtils.convertList(iPage.getRecords(), ShareDto.class));
    }

    @Override
    public FolderFileDto getShareFolderFile(String clientIp, QueryShareFolderBean queryShareFolderBean) {
        String key = RedisPrefix.SHARE_DOWNLOAD.getKey() + queryShareFolderBean.getVisitCode();
        DownloadModel downloadModel = RedisUtils.get(key);
        if (downloadModel == null) {
            throw FailCode.SHARE_VISIT_CODE_ERROR.getOperateException();
        }
        FolderFileDto folderFileDto = new FolderFileDto();
        ShareIdModel shareIdModel = getShareIdModelByShareId(downloadModel.getShareId());
        List<String> rootFolderIds = shareIdModel.getRootFolderIds();
        List<String> folderIds = shareIdModel.getFolderIds();
        List<String> rootFileIds = shareIdModel.getRootFileIds();
        List<String> fileIds = shareIdModel.getFileIds();
        String name = queryShareFolderBean.getName();
        // 查询出来的数据
        List<FileDto> fileList = new ArrayList<>();
        List<FolderDto> folderList = new ArrayList<>();
        if (queryShareFolderBean.getOpenQueryAll()) {
            List<FileEntity> files = new ArrayList<>();
            List<FolderEntity> folders = new ArrayList<>();
            // 查文件夹
            folderIds.addAll(rootFolderIds);
            if (folderIds.size() > 0) {
                FolderEntity folderEntity = new FolderEntity();
                folderEntity.setName(name);
                QueryWrapper<FolderEntity> queryWrapper = ServiceUtils.queryData(queryShareFolderBean, folderEntity).in("id", folderIds);
                folders = folderMapper.selectList(queryWrapper);
            }
            // 处理文件夹
            for (FolderEntity entity : folders) {
                FolderDto folderDto = ObjectUtils.convert(new FolderDto(), entity);
                folderDto.setPath(folderService.getPathByFolder(entity));
                folderList.add(folderDto);
            }
            //查文件
            if (fileIds.size() > 0) {
                fileIds.addAll(rootFileIds);
                FileEntity fileEntity = new FileEntity();
                fileEntity.setName(name);
                fileEntity.setStatus(EffectStatus.VALID.getStatus());
                QueryWrapper<FileEntity> query = ServiceUtils.queryData(queryShareFolderBean, fileEntity).in("id", fileIds);
                files = fileMapper.selectList(query);
            }
            // 处理文件夹
            for (FileEntity entity : files) {
                FileDto fileDto = ObjectUtils.convert(new FileDto(), entity);
                fileDto.setPath(folderService.getPathByFolderId(fileDto.getFolderId()));
                fileList.add(fileDto);
            }

            downloadModel.setFiles(files);
        } else {
            List<FileEntity> files = new ArrayList<>();
            List<FolderEntity> folders = new ArrayList<>();
            FolderEntity targetFolder = folderMapper.selectById(queryShareFolderBean.getFolderId());
            if (targetFolder != null) {
                //查文件夹
                if (folderIds.size() > 0) {
                    FolderEntity folderEntity = new FolderEntity();
                    folderEntity.setName(name);
                    folderEntity.setParentNode(targetFolder.getNode());
                    QueryWrapper<FolderEntity> queryWrapper = ServiceUtils.queryData(queryShareFolderBean, folderEntity);
                    queryWrapper.in("id", folderIds);
                    folders = folderMapper.selectList(queryWrapper);
                }
                //查文件
                if (fileIds.size() > 0) {
                    FileEntity fileEntity = new FileEntity();
                    fileEntity.setName(name);
                    fileEntity.setFolderId(targetFolder.getId());
                    fileEntity.setStatus(EffectStatus.VALID.getStatus());
                    QueryWrapper<FileEntity> query = ServiceUtils.queryData(queryShareFolderBean, fileEntity).in("id", fileIds);
                    files = fileMapper.selectList(query);
                }
            } else {
                //查文件夹
                if (rootFolderIds.size() > 0) {
                    FolderEntity folderEntity = new FolderEntity();
                    folderEntity.setName(name);
                    QueryWrapper<FolderEntity> queryWrapper = ServiceUtils.queryData(queryShareFolderBean, folderEntity);
                    queryWrapper.in("id", rootFolderIds);
                    folders = folderMapper.selectList(queryWrapper);
                }
                // 查文件
                if (rootFileIds.size() > 0) {
                    FileEntity fileEntity = new FileEntity();
                    fileEntity.setName(name);
                    fileEntity.setStatus(EffectStatus.VALID.getStatus());
                    QueryWrapper<FileEntity> query = ServiceUtils.queryData(queryShareFolderBean, fileEntity);
                    query.in("id", rootFileIds);
                    files = fileMapper.selectList(query);
                }
            }
            downloadModel.setFiles(files);
            fileList.addAll(ObjectUtils.convertList(files, FileDto.class));
            folderList.addAll(ObjectUtils.convertList(folders, FolderDto.class));
        }
        // 设置返回
        folderFileDto.setFiles(fileList);
        folderFileDto.setFolders(folderList);
        // 设置为有效允许下载
        RedisUtils.set(key, downloadModel, RedisTime.SHARE_DOWNLOAD_CACHE.getTime());
        // 设置下载url
        String visitCode = queryShareFolderBean.getVisitCode();
        fileService.setDownloadUrl(folderFileDto.getFiles(), "/share/" + visitCode + "/file/");
        return folderFileDto;
    }

    @Override
    @Transactional
    public void deleteUserShare(String userId, String shareId) {
        ShareEntity shareEntity = shareMapper.selectById(shareId);
        if (shareEntity == null) {
            throw FailCode.SHARE_INFO_NOT_EXIST.getOperateException();
        }
        // 验证数据权限
        if (!userId.equals(shareEntity.getUserId())) {
            throw FailCode.NOT_DATA_AUTHORITY.getOperateException();
        }
        QueryWrapper<ShareFolderFileEntity> queryWrapper = new QueryWrapper<>(new ShareFolderFileEntity(shareId));
        if (shareFolderFileMapper.selectList(queryWrapper).size() != 0) {
            if (!retBool(shareFolderFileMapper.delete(queryWrapper))) {
                throw FailCode.DELETE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
        }
        if (!this.removeById(shareId)) {
            throw FailCode.DELETE_FILE_SHARE_FILE_FAIL.getOperateException();
        }
    }

    @Override
    public ShareCodeDto verifyShareCode(String code, String drawCode) {
        ShareCodeDto shareCodeDto = new ShareCodeDto();
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setCode(code);
        shareEntity = shareMapper.selectOne(new QueryWrapper<>(shareEntity));
        if (shareEntity == null) {
            throw FailCode.SHARE_INFO_NOT_EXIST.getOperateException();
        }
        if (shareEntity.getDrawCode() != null && !shareEntity.getDrawCode().equals("")) {
            if (drawCode != null && !drawCode.equals("")) {
                if (shareEntity.getDrawCode() != null) {
                    if (!shareEntity.getDrawCode().equals(drawCode)) {
                        throw FailCode.DRAW_CODE_ERROR.getOperateException();
                    }
                }
            } else {
                shareCodeDto.setNeedDrawCode(true);
                return shareCodeDto;
            }
        }
        if (shareEntity.getValidTime() != 0) {
            if ((shareEntity.getCreateTime().getTime() + shareEntity.getValidTime()) < System.currentTimeMillis()) {
                throw FailCode.SHARE_FILE_INVALID.getOperateException();
            }
        }
        shareEntity.setBrowseNum(shareEntity.getBrowseNum() + 1);
        if (!this.updateById(shareEntity)) {
            throw FailCode.UPDATE_SHARE_FILE_FAIL.getOperateException();
        }
        // 设置共享下载
        DownloadModel downloadModel = new DownloadModel();
        downloadModel.setShareId(shareEntity.getId());
        String shareVisitCode = StringUtils.generateOnlyId(constants.getMachineId());
        String key = RedisPrefix.SHARE_DOWNLOAD.getKey() + shareVisitCode;
        RedisUtils.set(key, downloadModel, RedisTime.SHARE_DOWNLOAD_CACHE.getTime());
        // 设置返回参数
        shareCodeDto.setUserId(shareEntity.getUserId());
        shareCodeDto.setShareId(shareEntity.getId());
        shareCodeDto.setVisitCode(shareVisitCode);
        shareCodeDto.setNeedDrawCode(false);
        return shareCodeDto;
    }


    @Override
    public String getShareFolderSize(String shareId, String folderId) {
        // 获取下级文件夹及文件
        ShareEntity shareEntity = verifyShare(shareId);
        List<ShareFolderFileEntity> shareFiles = getShareFolderFile(shareEntity);
        // 查询共享的文件遍历
        List<String> shareFileIds = new ArrayList<>();
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            if (shareFolderFileEntity.getFileId() != null) {
                shareFileIds.add(shareFolderFileEntity.getFileId());
            }
        }
        // 计算大小
        return folderService.getFolderSize(folderId, shareFileIds);
    }


    @Override
    public ShareEntity verifyShare(String shareId) {
        ShareEntity shareEntity = shareMapper.selectById(shareId);
        if (shareEntity == null) {
            throw FailCode.SHARE_FILE_NOT_EXIST.getOperateException();
        }
        if (shareEntity.getValidTime() != 0) {
            if ((shareEntity.getCreateTime().getTime() + shareEntity.getValidTime()) < System.currentTimeMillis()) {
                throw FailCode.SHARE_FILE_INVALID.getOperateException();
            }
        }
        return shareEntity;
    }

    /**
     * 根据共享id获取共享关联信息
     *
     * @param shareEntity 共享信息
     * @return 关联集合
     */
    private List<ShareFolderFileEntity> getShareFolderFile(ShareEntity shareEntity) {
        //根据共享id查询共享关联
        List<ShareFolderFileEntity> shareFiles = shareFolderFileMapper.selectList(new QueryWrapper<>(new ShareFolderFileEntity(shareEntity.getId())));
        if (shareFiles.size() == 0) {
            throw FailCode.SHARE_FILE_NOT_EXIST.getOperateException();
        }
        return shareFiles;
    }

    @Override
    public ShareIdModel getShareIdModelByShareId(String shareId) {
        // 查询共享信息
        ShareEntity shareEntity = verifyShare(shareId);
        // 查询共享文件信息
        List<ShareFolderFileEntity> shareFiles = getShareFolderFile(shareEntity);
        ShareIdModel shareIdModel = new ShareIdModel();
        shareIdModel.setShareEntity(shareEntity);
        shareIdModel.setFileIds(new ArrayList<>());
        shareIdModel.setFolderIds(new ArrayList<>());
        shareIdModel.setRootFileIds(new ArrayList<>());
        shareIdModel.setRootFolderIds(new ArrayList<>());
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            if (shareFolderFileEntity.getFileId() != null) {
                String id = shareFolderFileEntity.getFileId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    shareIdModel.getRootFileIds().add(id);
                } else {
                    shareIdModel.getFileIds().add(id);
                }
            } else {
                String id = shareFolderFileEntity.getFolderId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    shareIdModel.getRootFolderIds().add(id);
                } else {
                    shareIdModel.getFolderIds().add(id);
                }
            }
        }
        return shareIdModel;
    }

    @Override
    public List<FolderDto> getShareParentFolderList(String shareId, String folderId) {
        ShareIdModel shareIdModel = getShareIdModelByShareId(shareId);
        List<String> folderIds = new ArrayList<>();
        folderIds.addAll(shareIdModel.getRootFolderIds());
        folderIds.addAll(shareIdModel.getFolderIds());
        List<FolderEntity> entities = folderService.getParentFolderList(folderId, folderIds);
        return ObjectUtils.convertList(entities, FolderDto.class);
    }
}
